﻿Public Class clsFIFO
#Region " IDisposable Support "
    Implements IDisposable
    Private disposedValue As Boolean = False        ' 偵測多餘的呼叫
    ' IDisposable
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                ' TODO: 明確呼叫時釋放 Managed 資源
                Me.FreeMemoryStream()
            End If
            ' TODO: 釋放共用的 Unmanaged 資源
        End If
        Me.disposedValue = True
    End Sub

    ' 由 Visual Basic 新增此程式碼以正確實作可處置的模式。
    Public Sub Dispose() Implements IDisposable.Dispose
        ' 請勿變更此程式碼。在以上的 Dispose 置入清除程式碼 (ByVal 視為布林值處置)。
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

    Private _DisposeFlag As Boolean = False
    Private _msBuf As IO.MemoryStream = Nothing

    Private Sub FreeMemoryStream()
        SyncLock _msBuf
            _DisposeFlag = True
            If (IsNothing(_msBuf) = False) Then
                _msBuf.Dispose()
                _msBuf = Nothing
            End If
        End SyncLock
    End Sub

    ReadOnly Property Length() As Long
        Get
            Dim rtnVal As Long = 0
            SyncLock _msBuf
                If _DisposeFlag = False AndAlso IsNothing(_msBuf) = False Then
                    rtnVal = _msBuf.Length
                End If
            End SyncLock
            Return rtnVal
        End Get
    End Property

    ReadOnly Property Read(ByVal Length As Integer) As Byte()
        Get
            Dim rtnVal() As Byte = Nothing
            SyncLock _msBuf
                If _DisposeFlag = False Then
                    If (IsNothing(_msBuf) = False) AndAlso (_msBuf.Length > 0) Then
                        Dim b() As Byte = _msBuf.ToArray
                        _msBuf.SetLength(0)
                        _msBuf.Position = 0

                        If b.Length > Length Then
                            ReDim rtnVal(Length - 1)
                            Array.Copy(b, rtnVal, Length)
                            _msBuf.Write(b, Length, (b.Length - Length))
                        Else
                            rtnVal = b
                        End If
                    End If
                End If
            End SyncLock
            Return rtnVal
        End Get
    End Property

    Public Sub Write(ByVal b() As Byte)
        SyncLock _msBuf
            If _DisposeFlag = False Then
                If (IsNothing(_msBuf) = False) Then
                    _msBuf.Position = _msBuf.Length
                    _msBuf.Write(b, 0, b.Length)
                End If
            End If
        End SyncLock
    End Sub

    Public Sub Clear()
        SyncLock _msBuf
            If _DisposeFlag = False Then
                If (IsNothing(_msBuf) = False) Then
                    _msBuf.SetLength(0)
                    _msBuf.Position = 0
                End If
            End If
        End SyncLock
    End Sub

    Public Sub New()
        _msBuf = New IO.MemoryStream
    End Sub
End Class